<?php
// +----------------------------------------------------------------------
// | 小牛Admin
// +----------------------------------------------------------------------
// | Website: www.xnadmin.cn
// +----------------------------------------------------------------------
// | Author: dav <85168163@qq.com>
// +----------------------------------------------------------------------

namespace app\common\lib;

class Ali
{
    private static $self;

    /**
     * 生成语音API
     */
    const TTS_URL = 'https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/tts?';

    /**
     * 语音识别API
     */
    const ASR_URL = 'http://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/asr?';

    /**
     * 音频编码格式
     */
    public $format = 'mp3';

    /**
     * 音频采样率，支持16000Hz/8000Hz，默认值：16000Hz。
     */
    public $sampleRate = 16000;

    /**
     * 语速
     */
    public $speechRate = -200;

    /**
     * 文件路径
     */
    public $filePath;

    /**
     *
     */
    public $dirPath = 'record' . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR;

    /**
     * 错误信息
     *
     * @var string
     * @author Ymob
     * @date 2021-04-22 19:51:21
     */
    public $error = '';

    private function __construct()
    {}

    public static function getClint()
    {
        if (self::$self == null) {
            self::$self = new Ali;
        }
        return self::$self;
    }

    /**
     * 语音合成
     *
     * @param string $text
     * @param string $fileName
     * @return bool
     * @author Ymob
     * @date 2021-04-22 19:39:32
     */
    public function tts($text = '', $filePath = null)
    {
        $param = [
            'appkey' => env('ali.app_key', ''),
            'token' => env('ali.token', ''),
            'text' => $text,
            'format' => $this->format,
            'sample_rate' => $this->sampleRate,
            'speech_rate' => $this->speechRate,
        ];

        $url = self::TTS_URL . \http_build_query($param);

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        $response = curl_exec($curl);

        if ($response == false) {
            curl_close($curl);
            $this->error = 'curl_exec failed!';
            return false;
        }
        $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
        $headers = substr($response, 0, $headerSize);
        $bodyContent = substr($response, $headerSize);
        curl_close($curl);

        if (stripos($headers, "Content-Type: audio/mpeg") != false || stripos($headers, "Content-Type:audio/mpeg") != false) {
            if ($filePath === null) {
                do {
                    $this->filePath = $this->dirPath . date('Y-m') . DIRECTORY_SEPARATOR . \md5(time()) . '.' . $this->format;
                } while (file_exists(\public_path() . $this->filePath));
            } else {
                $this->filePath = $filePath;
            }
            $filePath = \public_path() . $this->filePath;
            $dirPath = pathinfo($filePath, 3);
            if (!file_exists($dirPath)) {
                mkdir($dirPath, 0777, true);
            }
            file_put_contents($filePath, $bodyContent);
            return true;
        } else {
            $this->error = 'The POST request failed：' . $bodyContent;
            return false;
        }
    }

    /**
     * 语音识别
     *
     * @param string $filePath 录音文件
     * @param boolean $del  删除源文件
     * @return bool|string  成功返回字符 错误返回false
     * @author Ymob
     * @date 2021-04-22 21:02:43
     */
    public function asr($filePath, $del = false)
    {
        $audioContent = file_get_contents($filePath);
        if ($audioContent == false) {
            $this->error = '录音读取失败';
        } else {
            $param = [
                'appkey' => env('ali.app_key', ''),
                'format' => 'pcm',
                'sample_rate' => $this->sampleRate,
                'enable_voice_detection' => true,
                'enable_punctuation_prediction' => true,
                'enable_inverse_text_normalization' => true,
            ];

            $url = self::ASR_URL . \http_build_query($param);

            $curl = curl_init();
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($curl, CURLOPT_TIMEOUT, 120);
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_HTTPHEADER, [
                "X-NLS-Token:" . env('ali.token', ''),
                "Content-type: application/octet-stream",
                "Content-Length:" . strval(strlen($audioContent)),
            ]);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $audioContent);
            curl_setopt($curl, CURLOPT_NOBODY, false);

            $returnData = curl_exec($curl);

            curl_close($curl);

            if ($returnData == false) {
                $this->error = 'curl_exec failed!';
            } else {

                $resultArr = json_decode($returnData, true);

                if ($resultArr["status"] == 20000000) {
                    if ($del) {
                        @\unlink($filePath);
                    }

                    return $resultArr["result"];
                } else {
                    $this->error = '语音文件识别失败。' . $resultArr["status"] . $resultArr['message'];
                }
            }

        }

        if ($del) {
            @\unlink($filePath);
        }

        return false;

    }

    /**
     * 批量删除录音文件
     *
     * @return void
     * @author Ymob
     * @date 2021-04-23 00:07:55
     */
    public function removeRecord($arr)
    {
        foreach ($arr as $val) {
            @\unlink(\public_path() . $val);
        }
    }
}
